package pkg

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/alphadose/haxmap"
	log "github.com/sirupsen/logrus"
)

func GetPort(conn interface{}) (int, error) {
	switch c := conn.(type) {
	case net.Listener:
		if tcpAddr, ok := c.Addr().(*net.TCPAddr); ok {
			return tcpAddr.Port, nil
		}
	case net.PacketConn:
		if udpAddr, ok := c.LocalAddr().(*net.UDPAddr); ok {
			return udpAddr.Port, nil
		}
	}
	return 0, fmt.Errorf("unsupported type")
}

type AppStatus byte

func (er AppStatus) String() string {
	switch er {
	case RUNNING:
		return "RUNNING"
	case GRACEFUL_SHUTDOWN:
		return "GRACEFUL_SHUTDOWN"
	default:
		return "-"
	}
}

func NewAppStatus(v int32) AppStatus {
	switch v {
	case 0x0:
		return RUNNING
	case 0x1:
		return GRACEFUL_SHUTDOWN
	default:
		return 0
	}
}

const (
	RUNNING           AppStatus = 0x0 // 尖
	GRACEFUL_SHUTDOWN AppStatus = 0x1 // 峰
)

type AppServer struct {
	IsChild   bool                       // 是否是子进程
	Status    AppStatus                  // 应用状态
	Pid       int32                      // 进程ID
	Ppid      int32                      // 父进程ID
	Ports     []string                   // 监听的断开
	Listeners []net.Listener             // 监听器
	PortBinds *haxmap.Map[int32, string] // 设备端口绑定 map
	Wg        sync.WaitGroup             //
}

func (a *AppServer) Start(isChild bool) error {
	a.IsChild = isChild
	go a.HandleSignals()
	if !a.IsChild {
		for _, port := range a.Ports {
			ln, err := net.Listen("tcp", port)
			if err != nil {
				log.Warnf("%v", err)
				return err
			}
			a.Listeners = append(a.Listeners, ln)
			go a.Listen(ln)
		}
	} else {
		for fdOffset := 3; fdOffset < 5; fdOffset++ {
			f := os.NewFile(uintptr(fdOffset), "")
			ln, err := net.FileListener(f)
			if err != nil {
				log.Warnf("%v", err)
				return err
			}
			a.Listeners = append(a.Listeners, ln)
			go a.Listen(ln) // 启动连接处理
		}
	}
	return nil
}

func (a *AppServer) Listen(ln net.Listener) {
	defer ln.Close()
	defer a.Wg.Done()
	a.Wg.Add(1)

	log.WithFields(log.Fields{
		"Status": a.Status.String(),
		"PID":    a.Pid,
		"PPID":   a.Ppid,
		"Local":  ln.Addr().String(),
	}).Infof("Listen %s", ln.Addr().String())
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.WithFields(log.Fields{
				"Status": a.Status.String(),
				"PID":    a.Pid,
				"PPID":   a.Ppid,
				"Local":  ln.Addr().String(),
			}).Warnf("Error accepting: %v", err)
			return
		}
		// 连接处理
		go a.Work(conn)
	}
}

func (a *AppServer) Work(conn net.Conn) {
	defer conn.Close()
	defer a.Wg.Done()
	a.Wg.Add(1)
	// 处理消息
	buf := make([]byte, 1024)
	for {
		conn.SetReadDeadline(time.Now().Add(30 * time.Second))
		n, err := conn.Read(buf)
		if err != nil {
			log.WithFields(log.Fields{
				"Status": a.Status.String(),
				"PID":    a.Pid,
				"PPID":   a.Ppid,
				"Local":  conn.LocalAddr().String(),
				"Remote": conn.RemoteAddr().String(),
			}).Warnf("Error reading  %v", err)
			break
		}

		tmpBuf := make([]byte, n)
		copy(tmpBuf, buf[:n])
		log.WithFields(log.Fields{
			"Status": a.Status.String(),
			"PID":    a.Pid,
			"PPID":   a.Ppid,
			"Local":  conn.LocalAddr().String(),
			"Remote": conn.RemoteAddr().String(),
		}).Infof("Recv %x", tmpBuf)
	}
}

func (a *AppServer) HandleSignals() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGUSR2, syscall.SIGTERM) // SIGUSR2 触发热重启

	for sig := range ch {
		switch sig {
		case syscall.SIGUSR2:
			if err := a.ForkChild(); err != nil {
				log.Fatalf("Restart failed: %v", err)
			}
			a.GracefulShutdown() // 父进程优雅退出
			return
		case syscall.SIGTERM:
			a.GracefulShutdown()
			return
		}
	}
}

func (a *AppServer) ForkChild() error {
	// 收集所有 listener 的 fd
	files := make([]*os.File, 0, len(a.Listeners))
	for _, ln := range a.Listeners {
		f, _ := ln.(*net.TCPListener).File()   // 获取 fd
		syscall.SetNonblock(int(f.Fd()), true) // 修复唤醒问题
		files = append(files, f)
	}

	// 构建子进程命令
	args := []string{"-child"}
	cmd := exec.Command(os.Args[0], args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.ExtraFiles = files // 传递 fd 列表

	return cmd.Start() // 启动子进程
}

// 优雅退出
func (a *AppServer) GracefulShutdown() {
	a.Status = GRACEFUL_SHUTDOWN
	// 关闭端口监听
	for _, ln := range a.Listeners {
		go func(l net.Listener) {
			log.WithFields(log.Fields{
				"Status": a.Status.String(),
				"PID":    a.Pid,
				"PPID":   a.Ppid,
			}).Warnf("Close Listener %s", l.Addr().String())
			l.Close() // 显式关闭
		}(ln)
	}

	log.WithFields(log.Fields{
		"Status": a.Status.String(),
		"PID":    a.Pid,
		"PPID":   a.Ppid,
	}).Warnf("Wait Exit")
	a.Wg.Wait()

	log.WithFields(log.Fields{
		"Status": a.Status.String(),
		"PID":    a.Pid,
		"PPID":   a.Ppid,
	}).Warnf("Bye")
	os.Exit(0)
}

func NewAppServer(ports []string) *AppServer {
	return &AppServer{
		Status:    RUNNING,
		Ports:     ports,
		Pid:       int32(os.Getpid()),
		Ppid:      int32(os.Getppid()),
		Listeners: make([]net.Listener, 0, 2),
		PortBinds: haxmap.New[int32, string](),
	}
}
